package com.moyoutian.leetcode;

import java.util.*;

/**
 * 506. 相对名次
 * <p>
 * 给你一个长度为 n 的整数数组 score ，其中 score[i] 是第 i 位运动员在比赛中的得分。所有得分都 互不相同 。
 * <p>
 * <p>
 * 运动员将根据得分 决定名次 ，其中名次第 1 的运动员得分最高，名次第 2 的运动员得分第 2 高，依此类推。运动员的名次决定了他们的获奖情况：
 * <p>
 * <p>
 * 名次第 1 的运动员获金牌 "Gold Medal" 。
 * <p>
 * 名次第 2 的运动员获银牌 "Silver Medal" 。
 * <p>
 * 名次第 3 的运动员获铜牌 "Bronze Medal" 。
 * <p>
 * 从名次第 4 到第 n 的运动员，只能获得他们的名次编号（即，名次第 x 的运动员获得编号 "x"）。
 * <p>
 * 使用长度为 n 的数组 answer 返回获奖，其中 answer[i] 是第 i 位运动员的获奖情况。
 * <p>
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * 输入：score = [5,4,3,2,1]
 * <p>
 * 输出：["Gold Medal","Silver Medal","Bronze Medal","4","5"]
 * <p>
 * 解释：名次为 [1st, 2nd, 3rd, 4th, 5th] 。
 * <p>
 * 示例 2：
 * <p>
 * 输入：score = [10,3,8,9,4]
 * <p>
 * 输出：["Gold Medal","5","Bronze Medal","Silver Medal","4"]
 * <p>
 * 解释：名次为 [1st, 5th, 3rd, 2nd, 4th] 。
 * <p>
 * <p>
 * 提示：
 * <p>
 * <p>
 * n == score.length
 * <p>
 * 1 <= n <= 10^4
 * <p>
 * 0 <= score[i] <= 106
 * <p>
 * score 中的所有值 互不相同
 */
public class Demo506 {

    public static void main(String[] args) {
        int[] score = {10, 3, 8, 9, 4};
        System.out.println(Arrays.toString(findRelativeRanks(score)));
    }

    /**
     * 1 分析算法的时间复杂度    最少需要读取一遍才能知道每个人的排名，也就是最好时间复杂度O(n)
     * 2 方法1 排序打标签方法，这种办法需要先记录下标i（原），在排序，在把排序结果，根据原i放到返回的数组中。
     * 3 方法1升级版 hash 排序标签法，缩短排序时间。因为分数为1-10^4，1到10的四次方个不重复项。最多有10000个。
     *
     * @param score
     * @return
     */
    public static String[] findRelativeRanks(int[] score) {
        if (Objects.isNull(score) || score.length == 0) {
            return new String[0];
        }
        int max = score.length - 1;
        for (int i = 0; i < score.length; i++) {
            max = Math.max(max, score[i]);
        }
        if (max + 0.0 / score.length > 0.3 || max < 1000) {
            return findRelativeRanksByMax(score, max);
        } else {
            TreeMap<Integer, Integer> map = new TreeMap<>((o1, o2) -> o2 - o1);
            for (int i = 0; i < score.length; i++) {
                // 分值,位置
                map.put(score[i], i);
            }
            return findRelativeRanksMap(map);
        }
    }

    public static String[] findRelativeRanksMap(TreeMap<Integer, Integer> score) {
        String[] re = new String[score.size()];
        int count = 1;
        for (Map.Entry<Integer, Integer> integerIntegerEntry : score.entrySet()) {
            switch (count) {
                case 1:
                    re[integerIntegerEntry.getValue()] = "Gold Medal";
                    break;
                case 2:
                    re[integerIntegerEntry.getValue()] = "Silver Medal";
                    break;
                case 3:
                    re[integerIntegerEntry.getValue()] = "Bronze Medal";
                    break;
                default:
                    re[integerIntegerEntry.getValue()] = count + "";
                    break;
            }
            count++;
        }
        return re;
    }



    public static String[] findRelativeRanksByMax(int[] score, int tempLen) {
        if (Objects.isNull(score) || score.length == 0) {
            return new String[0];
        }
        int[] temp = new int[tempLen+1];
        Arrays.fill(temp, -1);
        String[] re = new String[score.length];
        for (int i = 0; i < score.length; i++) {
            // 分值=位置
            temp[score[i]] = i;
        }
        int count = 1;
        //名次
        for (int i = temp.length - 1; i >= 0; i--) {
            if (temp[i] > -1) {
                switch (count) {
                    case 1:
                        re[temp[i]] = "Gold Medal";
                        break;
                    case 2:
                        re[temp[i]] = "Silver Medal";
                        break;
                    case 3:
                        re[temp[i]] = "Bronze Medal";
                        break;
                    default:
                        re[temp[i]] = Integer.toString(count);
                        break;
                }
                count++;
            }
        }
        return re;
    }


    public static String[] findRelativeRanks2(int[] score) {
        int len = score.length ;
        int max = len;
        String[] re = new String[len];
        for (int i = 0; i < len; i++) {
            max = Math.max(max,score[i]);
        }
        int[] temp = new int[max+1];
        for (int i = 0; i < len; i++) {
            // 分值=位置
            temp[score[i]] = i+1;
        }
        int count = 1;
        //名次
        for (int i = max; i >= 0; i--) {
            if (temp[i] != 0) {
                switch (count) {
                    case 1:
                        re[temp[i]-1] = "Gold Medal";
                        break;
                    case 2:
                        re[temp[i]-1] = "Silver Medal";
                        break;
                    case 3:
                        re[temp[i]-1] = "Bronze Medal";
                        break;
                    default:
                        re[temp[i]-1] = count + "";
                        break;
                }
                count++;
            }
        }
        return re;
    }
}
